﻿using LightCAD.Core.Element3d;

namespace LightCAD.Model
{

    public class Prism3dAction : Solid3dAction
    {
        private LcPrism Prism = null;
        private int Side = 6;
        private bool IsInnerCircle = false;
        public Prism3dAction(IDocumentEditor docEditor) : base(docEditor)
        {
            this.commandCtrl.WriteInfo("命令：Prism");
        } 
        public async void ExecCreate(string[] args = null)
        {
            StartAction();
            Vector3 startP = null;
            Vector3 endP = null;
            PointInputer3d pointer = new PointInputer3d(docEditor);
            pointer.isOnlyPoint = false;
        Step0:
            var result0 = await pointer.Execute("输入侧面数<6>:");
            if (result0.IsCancelled)
            {
                goto End;
            }
            else if (!string.IsNullOrEmpty(result0.Option) && int.TryParse(result0.Option, out int count)&&count>2) {
                Side = count;
            }
            else {
                Side = 6;
            }
        Step1:
            var result1 = await pointer.Execute("输入选项 [内接于圆(I)/外切于圆(C)]<I>:");
            if (result1.IsCancelled)
            {
                goto End;
            }
            else if (!string.IsNullOrEmpty(result1.Option))
            {
                if (result1.Option.Trim().ToUpper()=="I")
                {
                    IsInnerCircle = true;
                }
                else if (result1.Option.Trim().ToUpper() == "C")
                {
                    IsInnerCircle = false;
                }
                else
                {
                    goto Step1;
                }
            }
            else
            {
                IsInnerCircle = true;
            }
            pointer.Prompt("请指定棱柱的中心点:");
            FaceInputerResult pr = null;
            PlanarSurface3d plane = null;
            LcSolid3d solidEle = null;
            double pullDist = 0;
            bool startPush = false;
            this.model3dRuntime.EnableCameraControl(false);
            this.snap3dRuntime.AddSnapPlanes(new ListEx<Plane>
            {
                new Plane().SetFromNormalAndCoplanarPoint(new Vector3(0, 0, 1), new Vector3())
            });
            void onMouseEvent(string name, MouseEventRuntime mer)
            {
                if (name == "Move")
                {
                    if (!startPush)
                    {
                        if (startP == null)
                        {
                            return;
                        }

                        endP = this.snap3dRuntime.SnapPoint.Clone();
                        if (endP != null)
                        {
                            this.CreateOrUpdatePrism(startP, endP, 1);
                        }
                    }
                    else
                    {
                        if (solidEle != null && pr != null&& this.snap3dRuntime.SnapPoint!=null)
                        {
                            Move(this.snap3dRuntime.SnapPoint);
                        }
                    }
                }
                else if (name == "Down")
                {
                    if (startP == null)
                    {
                        startP = this.snap3dRuntime.SnapPoint.Clone();
                    }else
                    if (!startPush)
                    {
                        startPush = true;
                        var topFace = this.Prism.Solid.TopoFaceModel.Surfaces[this.Prism.Solid.TopoFaceModel.Surfaces.Count-2];
                        pr = new FaceInputerResult()
                        {
                            Surface = topFace,
                            Element = this.Prism,
                            SnapPoint = this.snap3dRuntime.SnapPoint.Clone()
                        };

                        plane = pr.Surface as PlanarSurface3d;
                        solidEle = pr.Element as LcSolid3d;
                        this.snap3dRuntime.ClearSnapPlanes();
                        var camera = this.snap3dRuntime.GetCamera();
                        var yAxis = camera.getWorldDirection().Negate().Cross(plane.Normal).Normalize();
                        var zAxis = plane.Normal.Clone().Cross(yAxis).Normalize();
                        this.snap3dRuntime.AddSnapPlanes(new ListEx<Plane>
                        {
                            new Plane().SetFromNormalAndCoplanarPoint(zAxis,pr.SnapPoint.Clone())
                        });
                    }
                    else if (startPush)
                    {
                        this.snap3dRuntime.EndSnaping();
                        this.model3dRuntime.Control.DetachEvents(null, null, onMouseEvent, null, null, null, null);
                        this.snap3dRuntime.ClearSnapPlanes();
                        this.model3dRuntime.EnableCameraControl(true);
                    }
                }
            }

            void Move(Vector3 target)
            {
                CreateOrUpdatePrism(startP,endP, target.Z);
            }
            this.snap3dRuntime.StartSnaping(SnapFilterType.OnlyPlane);
            this.model3dRuntime.Control.AttachEvents(null, null, onMouseEvent, null, null, null, null);
        End:
            EndAction();
        }
        public void CreateOrUpdatePrism(Vector3 start, Vector3 end, double depth)
        {
            if (this.Prism != null)
            {
                this.docRt.Document.ModelSpace.RemoveElement(this.Prism);
            }
            var mats = new LcMaterial[3]
            {
                new LcMaterial() { Color = new Color(0xff0000) },
                new LcMaterial() { Color = new Color(0x00ff00) },
                new LcMaterial() { Color = new Color(0x0000ff) },
            };
            Vector3 cenOffset = (end - start).MulScalar(0.5); 
            double distance = end.DistanceTo(start);
            this.Prism = new LcPrism(Side, distance, distance, depth,this.IsInnerCircle, false, mats);
            this.Prism.Solid.Topoable = true;
            this.Prism.Initilize(this.docRt.Document);
            this.Prism.Rt3DAction = this;
            this.Prism.Position = start.Clone();
            this.Prism.UpdateMatrix();
            this.docRt.Document.ModelSpace.InsertElement(this.Prism);
        }
    }
}
